# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#

import re
import sys
from os import environ, path

sys.path.insert(0, "..")


def current_version() -> str:
    root = path.dirname(path.dirname(path.abspath(__file__)))
    with open(f"{root}/mlrun/__init__.py") as fp:
        for line in fp:
            # __version__ = '0.4.6'
            match = re.search(r"__version__\s*=\s*'([^']+)'", line)
            if match:
                return match.group(1)
    return "UNKNOWN"


# -- Project information -----------------------------------------------------

project = "mlrun"
copyright = "2020-2025, Iguazio"
author = "Iguazio"

master_doc = "contents"

# The full version, including alpha/beta/rc tags
release = current_version()

# The short X.Y version
version = release
version = version[: version.rfind(".")]

# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    "myst_nb",
    "sphinx.ext.napoleon",
    "sphinx.ext.autodoc",
    "sphinx.ext.autosummary",
    "sphinx.ext.todo",
    "sphinx.ext.viewcode",
    "sphinx.ext.extlinks",
    "sphinx_copybutton",
    "sphinx_togglebutton",
    "sphinx_design",
    "sphinx_reredirects",
    "versionwarning.extension",
    "sphinxcontrib.mermaid",
    "sphinx_image_inverter",
]

# Add any paths that contain templates here, relative to this directory.
templates_path = [
    "_templates",
]
extlinks = {
    "requirements": (
        "https://github.com/mlrun/mlrun/blob/%s/requirements.txt",
        "requirements.txt in v%s",
    )
}

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = "en"

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = [
    "_build/**",
    ".venv/**",
    "CONTRIBUTING.md",
]

source_suffix = {
    ".rst": "restructuredtext",
    ".ipynb": "myst-nb",
    ".myst": "myst-nb",
    ".md": "myst-nb",
}

nitpicky = False  # TODO: Change to `True`.

# versionwarning configuration
versionwarning_default_message = (
    "This is not the latest documentation. See {stable} instead."
)

versionwarning_message_placeholder = "stable"

# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.

html_theme = "sphinx_book_theme"
html_title = ""
html_logo = "./MLRun_Character.png"
html_favicon = "./favicon.ico"
nb_execution_mode = "off"
html_sourcelink_suffix = ""
autoclass_content = "both"

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
html_css_files = ["custom.css"]

html_theme_options = {
    "github_url": "https://github.com/mlrun/mlrun",
    "repository_url": "https://github.com/mlrun/mlrun",
    "use_repository_button": True,
    "use_issues_button": True,
    "use_edit_page_button": True,
    "path_to_docs": "docs",
    "home_page_in_toc": False,
    "repository_branch": "development",
    "show_navbar_depth": 1,
    # "extra_navbar": 'By <a href="https://www.iguazio.com/">Iguazio</a>',  # https://github.com/executablebooks/sphinx-book-theme/issues/810
    "extra_footer": "",
}

html_sidebars = {
    "**": ["navbar-logo.html", "search-button-field.html", "sbt-sidebar-nav.html"]
}

copybutton_selector = "div:not(.output) > div.highlight pre"

myst_enable_extensions = [
    "colon_fence",
    "deflist",
    "html_image",
    "html_admonition",
    "replacements",
    "linkify",
    "substitution",
]
myst_url_schemes = ("http", "https", "mailto")
myst_heading_anchors = 5
myst_all_links_external = False
myst_xref_missing = "ignore"

# These substitutions point to the relevant mlrun docs for the current CE version
myst_substitutions = {
    "version": "1.9.2",
    "ceversion": "v0.9.0",
    "releasedocumentation": "docs.mlrun.org/en/stable/index.html",
}

# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
# Add here external imports:
autodoc_mock_imports = [
    "plotly",
    "sklearn",
    "tensorflow",
    "tensorboard",
    "torch",
    "tqdm",
    "lightgbm",
    "xgboost",
    "onnx",
]

redirects = {
    "runtimes/functions-architecture": "runtimes/functions.html",
    "monitoring/initial-setup-configuration": "monitoring/model-monitoring-deployment.html",
    "tutorials/05-batch-infer": "tutorials/06-batch-infer.html",
    "tutorials/06-model-monitoring": "tutorials/05-model-monitoring.html",
    "monitoring/models": "../model-monitoring/monitoring-models.html",
    "monitoring/monitoring": "../model-monitoring.html",
    "monitoring/monitoring-deployment": "../model-monitoring/model-monitoring-deployment.html",
    "monitoring/legacy-model-monitoring": "../model-monitoring/legacy-model-monitoring.html",
    "concepts/monitoring": "model-monitoring.html",
    "monitoring/index": "../model-monitoring/index.html",
    "monitoring/model-monitoring": "model-monitoring/index.html",
}

smartquotes = False

# Do not invert all images by default in dark mode
inverter_all = False

linkcheck_ignore = [
    # Ignore all the links to local files
    r"^(?!https?://).*",
    # linkcheck doesn't work well with relative paths on github which contain anchor, so ignore them
    r"https:\/\/github.com/.*#.*$",
    # open ai often blocks access and returns 403
    r"https:\/\/platform\.openai\.com\/.*",
    r"https:\/\/openai\.com\/.*",
    # Single links to ignore
    "./workflow.py",
    "http://workflow.py",
    "alerts-notifications",
    "project.yaml",
    "http://function.py",
    "http://localhost:30040",
    "https://dev.mysql.com/doc/refman/8.0/en/keywords.html",
    "https://www.kaggle.com/code/jsylas/python-version-of-top-ten-rank-r-22-m-2-88/data?select=train.csv",
    "http://test-milvus.milvus.svc.cluster.local:19530",
    "https://docs.confident-ai.com/docs/",
    # Returns 404 though link is valid
    "https://docs.databricks.com/aws/en/reference/jobs-2.0-api",
    # can be removed after v1.8.0 is released:
    "https://docs.mlrun.org/en/stable/api/mlrun.datastore/index.html#mlrun.datastore.datastore_profile.TDEngineDatastoreProfile",
    # Mckinsey restricted
    "https://ollama.com/download",
    "https://ollama.com/library/llama3",
    # Can be deleted after v1.8.0 is GA
    "https://docs.mlrun.org/en/stable/api/mlrun.projects/index.html#mlrun.projects.MlrunProject.get_vector_store_collection",
    "https://docs.mlrun.org/en/stable/api/mlrun.projects/index.html#mlrun.projects.MlrunProject.log_document",
    "https://docs.mlrun.org/en/stable/api/mlrun.datastore/index.html#mlrun.datastore.vectorstore.VectorStoreCollection.add_artifacts",
    "https://docs.mlrun.org/en/stable/api/mlrun.datastore/index.html#mlrun.datastore.datastore_profile.ConfigProfile",
    "https://docs.mlrun.org/en/stable/api/mlrun.artifacts/mlrun.artifacts.document.html#mlrun.artifacts.document.MLRunLoader",
    "https://docs.mlrun.org/en/stable/api/mlrun.projects/index.html#mlrun.projects.MlrunProject.get_config_profile_attributes",
    "https://docs.mlrun.org/en/stable/api/mlrun.projects/index.html#mlrun.projects.MlrunProject.get_config_profile_attributes",
    "https://docs.mlrun.org/en/stable/api/mlrun.artifacts/mlrun.artifacts.document.html#mlrun.artifacts.document.DocumentLoaderSpec",
    "https://docs.confident-ai.com/docs/getting-started",
    "https://docs.confident-ai.com/docs/metrics-contextual-recall",
    "https://docs.confident-ai.com/docs/metrics-answer-relevancy",
    "https://docs.confident-ai.com/docs/metrics-contextual-precision",
    "https://docs.confident-ai.com/docs/metrics-contextual-relevancy",
    "https://docs.confident-ai.com/docs/metrics-faithfulness",
    # ignore links to kubernetes.io, since they often block the traffic
    r"https://kubernetes.io/.*",
]

# -- Autosummary -------------------------------------------------------------

autosummary_generate = True


def copy_doc(src, dest, title=""):
    """Copy over .md documentation from other parts of the project"""
    with open(dest, "w") as out:
        with open(src) as fp:
            changed = False
            for line in fp:
                if title and re.match("^# .*", line) and not changed:
                    line = f"# {title}"
                    changed = True
                out.write(line)


def setup(app):
    # This avoids generating llms.txt for every branch/tag build,
    # limiting it to builds of public-facing versions ("stable") and PR previews ("external")
    if (
        environ.get("READTHEDOCS_VERSION") == "stable"
        or environ.get("READTHEDOCS_VERSION_TYPE") == "external"
    ):
        app.connect("build-finished", create_llms_txt)


# default header for llms.txt file
default_prefix = """# MLRun
MLRun is an open source AI orchestration platform for quickly building and managing continuous (gen) AI applications
across their lifecycle.

"""


def create_llms_txt(app, exception):
    """
    Generate the llms.txt file with a default header and content from the specified source file.

    This function is called after the Sphinx build process is finished. It generates an llms.txt file
    in the output directory, containing a default header and content extracted from the "contents.rst" file.
    """
    # Add the directory containing llms.py to the system path
    sys.path.insert(0, path.abspath("."))
    from llms import generate_llm_txt

    output_path = path.join(app.outdir, "llms.txt")
    generate_llm_txt(".", prefix=default_prefix, output_path=output_path)


#   project_root = path.dirname(path.dirname(path.abspath(__file__)))
#   copy_doc(f"{project_root}/examples/remote.md", "external/remote.md")
#    copy_doc(
#        f'{project_root}/README.md', 'external/general.md', 'Introduction')
#    copy_doc(
#        f'{project_root}/hack/local/README.md', 'external/install.md')
#    check_call([
#        'jupyter', 'nbconvert',
#        '--output', f'{project_root}/docs/external/basics.html',
#        f'{project_root}/examples/mlrun_basics.ipynb',
#    ])
